package jdbc2;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

/**
 * 实现功能
 * 提供连接池获取连接
 * 提供事务连接
 * 提供开关事务
 * 提供释放非事务连接
 * 支持多线程并发访问
 * Created by kevin on 2020/3/29.
 */
public class JdbcUtils {
    //加载配置文件的默认配置,需要配置c3p0-config.xml(放在src/main/Resource目录下即可)
    private static ComboPooledDataSource dataSource = new ComboPooledDataSource();

    //事务专用连接
//    private static Connection connection = null;

    //由原来的一个对象成为了一个存储对象的容器
    private static ThreadLocal<Connection> connectionThreadLocal = new InheritableThreadLocal<Connection>();
    /**
     * 如果connection不为null那么返回的就是事务专用连接
     * @return
     * @throws SQLException
     */
    public static Connection getConnection() throws SQLException{
        Connection connection = connectionThreadLocal.get();
        if(connection!=null){
            return connection;
        }else{
            return dataSource.getConnection();
        }
    }

    public static DataSource getDataSource(){
        return dataSource;
    }

    /**
     * 开启事务
     * 1.获取一个Connection,设置它的setAutoCommit(false)
     * 2.还要保证dao中使用的连接是我们刚刚创建的
     */
    public static void beginTransaction(){
        Connection connection = connectionThreadLocal.get();//获取当前线程专用连接
        try {
            if(connection!=null){
                throw new SQLException("已经开启事务,请勿重复操作");
            }
            connection = getConnection();
            connection.setAutoCommit(false);
            connectionThreadLocal.set(connection);//存储当前线程专用连接
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 提交事务
     * 1.获取beginTransaction提供的Connection,然后调用commit方法
     */
    public static void commitTransaction(){
        Connection connection = connectionThreadLocal.get();//获取当前线程专用连接
        try {
            if(connection==null){
                throw new SQLException("还没有开启事务!不能提交");
            }
            connection.commit();
            connection.close();
            connectionThreadLocal.remove();//移除当前线程专用连接
//            connection = null;//必须清空值否则下次会得到一个已经关闭的连接
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 回滚事务
     * 1.获取beginTransaction提供的Connection,然后调用了rollback方法
     */
    public static void rollbackTransaction(){
        Connection connection = connectionThreadLocal.get();//获取当前线程专用连接
        try {
            if(connection==null){
                throw new SQLException("还没有开启事务!不能回滚");
            }
            connection.rollback();
            connection.close();
            connectionThreadLocal.remove();//移除当前线程专用连接
//            connection= null;//必须清空值否则下次会得到一个已经关闭的连接
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 释放非事务专用连接
     * 判断它是不是事务专用连接,如果是,不关闭
     * 如果不是,就进行关闭
     *
     */
    public static void releaseConnection(Connection inCon) throws SQLException{
        Connection connection = connectionThreadLocal.get();//获取当前线程专用连接
        //如果connection == null 说明现在没有事务,那么connection一定不是事务专用
        if(connection == null){
            inCon.close();
        }
        //如果connection!=null 说明有事务,那么需要判断连接参数是否与connection相等
        //若不等说明参数连接不是事务专用连接
        if(connection!=inCon){
            inCon.close();
        }
    }
}
